package cc.rengu.igas.channel.upac.core.service.base;

import cc.rengu.igas.channel.upac.common.constant.UpacConfigConstant;
import cc.rengu.igas.channel.upac.common.constant.UpacParamConstant;
import cc.rengu.igas.channel.upac.common.constant.UpacTreeNodeConstant;
import cc.rengu.igas.channel.upac.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.upac.common.util.UpacSecurityUtil;
import cc.rengu.igas.channel.upac.core.model.ChnlBizResponse;
import cc.rengu.igas.channel.upac.facade.base.BaseRequest;
import cc.rengu.igas.channel.upac.facade.bean.CustomerInfo;
import cc.rengu.igas.channel.upac.facade.bean.PayerInfo;
import cc.rengu.igas.channel.upac.facade.bean.RiskCtrlInfo;
import cc.rengu.igas.channel.upac.facade.bean.TokenPayInfo;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.*;
import cc.rengu.oltp.service.common.dao.impl.*;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.RSAUtil;
import cc.rengu.oltp.utility.util.RedisUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.cache.UnifiedCache;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 网关支付业务处理基类
 */
public abstract class GatewayPayService<T> extends RadpService {
    @Override
    protected int bizInit(String s) {
        return 0;
    }

    @Override
    protected int bizProcess(String s, int i) {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
            /* Step1：通道(交易)权限检查 */
            rglog.info("---------------> 通道(交易)权限检查 <---------------");
            channelPermissionCheck();
            /* Step2：业务处理前实现接口 */
            rglog.info("---------------> 业务处理前处理 <---------------");
            T request = beforeBizProcess();
            rglog.error("请求对象request:<{}>", JSON.toJSONString(request));
            /* Step3：公共字段统一处理 */

            /* Step4：业务逻辑处理 */
            rglog.info("---------------> 业务逻辑处理 <---------------");
            ChnlBizResponse response = callBizService(request);
            /* Step4：业务处理后实现接口 */
            rglog.info("---------------> 业务处理后处理 <---------------");
            afterBizProcess(response);
        } catch (Exception e) {
            String respCode;
            String respDesc;
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
            rglog.error("业务异常信息:<{}>", byteArrayOutputStream.toString());
            if (e instanceof BizException) {
                respCode = ((BizException) e).getCode();
                respDesc = e.getMessage();
                rglog.error("业务处理失败，业务返回码:<{}>，业务返回信息:<{}>", respCode, respDesc);
            } else {
                rglog.error("系统处理失败，返回信息:<{}>", e);
                respCode = OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode();
                respDesc = OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc();
            }
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, respCode);
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, respDesc);
            } catch (Exception ex) {
                ex.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
                rglog.error("设置节点值异常信息:<{}>", byteArrayOutputStream.toString());
                return -1;
            }

        }
        return 0;
    }

    @Override
    protected int bizTerminate(String s) {
        return 0;
    }

    /**
     * 业务调用前处理
     *
     * @return 业务处理请求结构
     */
    protected abstract T beforeBizProcess() throws Exception;

    /**
     * 业务处理服务调用
     *
     * @param request 业务处理信息
     * @return 业务处理应答结果
     */
    protected abstract ChnlBizResponse callBizService(T request) throws Exception;

    /**
     * 业务调用后处理
     *
     * @param response 业务响应结果
     */
    protected abstract void afterBizProcess(ChnlBizResponse response) throws Exception;

    /**
     * 通道、交易权限权限
     *
     * @throws Exception 业务处理异常
     */
    private void channelPermissionCheck() throws Exception {
        BaseRequest baseRequest = new BaseRequest();
        ConvertUtil.convertOutput(baseRequest);
        rglog.error("请求报文头:<{}>", JSON.toJSONString(baseRequest));
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String instId = baseRequest.getHeader().getInstId();
        String txnNum = baseRequest.getHeader().getTxnNum();
        String prodType = xmlTreeUtil.getXmlTreeStringValue(UpacTreeNodeConstant.PROD_TYPE);
        /* 通道状态检查 */
        String dstChannelKey = instId + ChannelEnum.UPAC.getChannelType();
        DstChannelInfo dstChannelInfo = JSON.parseObject(RedisUtil.hashGet(AppParamConstant.CHANNEL_ISS_INFO_CACHE, dstChannelKey), DstChannelInfo.class);
        if (null == dstChannelInfo) {
            DstChannelInfoMapper dstChannelInfoMapper = new DstChannelInfoMapperImpl();
            dstChannelInfo = dstChannelInfoMapper.selectDstChannelInfoByPrimaryKey(instId, ChannelEnum.UPAC.getChannelType());
        }
        if (null == dstChannelInfo || !dstChannelInfo.getDstChannelStatus().equalsIgnoreCase(AppParamConstant.YES)) {
            rglog.error("支付渠道<{}-{}>未配置或已停用！", ChannelEnum.UPAC.getChannelType(), (null == dstChannelInfo) ? "" : dstChannelInfo.getDstChannelName());
            throw new BizException(OltpRpcdEnum.CHANNEL_DISABLED);
        }
        xmlTreeUtil.setXmlTreeObjectValue(UpacTreeNodeConstant.DST_CHANNEL_INFO, dstChannelInfo);

        /*获取通道参数配置*/
        DstChannelCfgMapper dstChannelCfgMapper = new DstChannelCfgMapperImpl();
        DstChannelCfg dstChannelCfg = dstChannelCfgMapper.selectDstChannelCfgByPrimaryKey(instId, ChannelEnum.UPAC.getChannelType(), prodType);
        if (dstChannelCfg == null) {
            throw new BizException(OltpRpcdEnum.CHANNEL_DISABLED);
        } else {
            xmlTreeUtil.setXmlTreeObjectValue(UpacTreeNodeConstant.DST_CHANNEL_CFG, dstChannelCfg);
        }

        String dstChannelAuthKey = instId.trim() + ChannelEnum.UPAC.getChannelType() + txnNum.trim();
        DstTxnAuthCfg dstTxnAuthCfg = JSON.parseObject(RedisUtil.hashGet(AppParamConstant.CHANNEL_TXN_CACHE, dstChannelAuthKey), DstTxnAuthCfg.class);
        if (null == dstTxnAuthCfg) {
            DstTxnAuthCfgMapper dstTxnAuthCfgMapper = new DstTxnAuthCfgMapperImpl();
            dstTxnAuthCfg = dstTxnAuthCfgMapper.selectDstTxnAuthCfgByPrimaryKey(instId, ChannelEnum.UPAC.getChannelType(), txnNum.trim());
        }
        if (null == dstTxnAuthCfg || !dstTxnAuthCfg.getSupportFlag().equalsIgnoreCase(AppParamConstant.YES)) {
            rglog.error("支付通道<{}-{}>不支持此交易，通道交易码:<{}>", dstChannelInfo.getDstChannelId(), dstChannelInfo.getDstChannelName(), txnNum);
            throw new BizException(OltpRpcdEnum.TRANS_NOT_SUPPORT);
        }
        if (dstTxnAuthCfg.getMsgRegisterFlag() != null && !dstTxnAuthCfg.getMsgRegisterFlag().isEmpty()) {
            xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.MSG_REG_FLAG, dstTxnAuthCfg.getMsgRegisterFlag());
        }

        if (dstChannelCfg.getOtherConfParam() != null) {
            JSONObject jsonObject = JSONObject.parseObject(dstChannelCfg.getOtherConfParam());
            if (jsonObject.get(UpacParamConstant.ENC_FLAG) != null) {
                xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.ACCT_ENC_FLAG, (String) jsonObject.get(UpacParamConstant.ENC_FLAG));
            } else {
                rglog.error("未配置账户是否加密，默认不加密");
            }
        } else {
            rglog.error("未配置账户是否加密，默认不加密");
        }
    }

    /**
     * 敏感信息加密处理
     *
     * @param encData 加密数据
     * @throws Exception 异常
     */
    protected String encryptData(String encData) throws Exception {
        if (encData == null) {
            rglog.error("加密字段为null");
            return null;
        }
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        CertInfo encryptCertInfo = null;
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
        if (instId == null) {
            instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_INST_ID);
        }
        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(UpacTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);
        DstChannelCfg dstChannelCfg = (DstChannelCfg) xmlTreeUtil.getXmlTreeObjectValue(UpacTreeNodeConstant.DST_CHANNEL_CFG, DstChannelCfg.class);
        String encoding = UpacParamConstant.UTF_8_ENCODING;
        /* 获取敏感信息解密证书 */
        List<SecPlanInfo> secPlanInfoList = null;
        String secPlanInfoListString = xmlTreeUtil.getXmlTreeStringValue(UpacTreeNodeConstant.SEC_PLAN_INFO_LIST);
        if (secPlanInfoListString == null) {
            /* 根据通道安全计划获取安全计划 */
            SecPlanInfoMapper secPlanInfoMapper = new SecPlanInfoMapperImpl();
            secPlanInfoList = secPlanInfoMapper.selectSecPlanInfoBySecPlanId(instId, dstChannelCfg.getSecPlanId());
            if (null != secPlanInfoList && !secPlanInfoList.isEmpty()) {
                xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.SEC_PLAN_INFO_LIST, JSON.toJSONString(secPlanInfoList));
            } else {
                rglog.error("获取通道解密密钥证书失败！");
                return null;
            }
        } else {
            secPlanInfoList = JSONArray.parseArray(secPlanInfoListString, SecPlanInfo.class);
        }
        Optional<SecPlanInfo> encryptSecPlanOpt = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(UpacParamConstant.ENCRYPT_CERT_TYPE)).findFirst();
        if (encryptSecPlanOpt.isPresent()) {
            CertInfoMapper certInfoMapper = new CertInfoMapperImpl();
            encryptCertInfo = certInfoMapper.selectCertInfoByPrimaryKey(instId + encryptSecPlanOpt.get().getSecPlanId() + encryptSecPlanOpt.get().getSecPlanType());
            if (encryptCertInfo == null) {
                rglog.error("获取通道解密密钥证书失败！");
                return null;
            } else {
                xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.encryptCertId, encryptCertInfo.getCertId());
            }
        }
        if ("0".equals(encryptCertInfo.getCertSaveType())) {
            return UpacSecurityUtil.encryptData(encData, encryptCertInfo.getCertValue(), encoding);
        } else {
            /*优先从系统缓存读取*/
            RSAPublicKey publicKey = null;
            String priKeyStr = (String) UnifiedCache.get(UpacParamConstant.CERT_KEY_CACHE, encryptCertInfo.getCertIndex());
            if (priKeyStr != null) {
                publicKey = RSAUtil.getPublicKeyFromBase64String(priKeyStr);
            } else {
                /*从本地证书文件获取*/
                publicKey = RSAUtil.getPublicKeyFromCertFile(encryptCertInfo.getCertSavePath());
                if (publicKey != null) {
                    if (UnifiedCache.set(UpacParamConstant.CERT_KEY_CACHE, encryptCertInfo.getCertIndex(), Base64.encodeBase64String(publicKey.getEncoded())) != 0) {
                        rglog.error("设置证书缓存索引号{}缓存失败", encryptCertInfo.getCertIndex());
                    }
                }
            }
            return UpacSecurityUtil.encryptData(encData, publicKey, encoding);
        }
    }

    /**
     * 敏感信息解密处理
     *
     * @param encData 加密数据
     * @throws Exception 异常
     */
    protected String descryptData(String encData) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        CertInfo encryptCertInfo = null;
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
        if (instId == null) {
            instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_INST_ID);
        }
        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(UpacTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);
        String encoding = UpacParamConstant.UTF_8_ENCODING;
        /* 获取敏感信息解密证书 */
        List<SecPlanInfo> secPlanInfoList = null;
        String secPlanInfoListString = xmlTreeUtil.getXmlTreeStringValue(UpacTreeNodeConstant.SEC_PLAN_INFO_LIST);
        if (secPlanInfoListString == null) {
            /* 根据通道安全计划获取安全计划 */
            SecPlanInfoMapper secPlanInfoMapper = new SecPlanInfoMapperImpl();
            secPlanInfoList = secPlanInfoMapper.selectSecPlanInfoBySecPlanId(instId, dstChannelInfo.getSecPlanId());
            if (null != secPlanInfoList && !secPlanInfoList.isEmpty()) {
                xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.SEC_PLAN_INFO_LIST, JSON.toJSONString(secPlanInfoList));
            } else {
                rglog.error("获取通道解密密钥证书失败！");
                return null;
            }
        } else {
            secPlanInfoList = JSONArray.parseArray(secPlanInfoListString, SecPlanInfo.class);
        }
        Optional<SecPlanInfo> encryptSecPlanOpt = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(UpacParamConstant.DECRYPT_CERT_TYPE)).findFirst();
        if (encryptSecPlanOpt.isPresent()) {
            CertInfoMapper certInfoMapper = new CertInfoMapperImpl();
            encryptCertInfo = certInfoMapper.selectCertInfoByPrimaryKey(instId + encryptSecPlanOpt.get().getSecPlanId() + encryptSecPlanOpt.get().getSecPlanType());
        }
        if ("0".equals(encryptCertInfo.getCertSaveType())) {
            return UpacSecurityUtil.decryptData(encData, encryptCertInfo.getCertValue(), encoding);
        } else {
            /*优先从系统缓存读取*/
            RSAPrivateKey privateKey = null;
            String priKeyStr = (String) UnifiedCache.get(UpacParamConstant.CERT_KEY_CACHE, encryptCertInfo.getCertIndex());
            if (priKeyStr != null) {
                privateKey = RSAUtil.getPrivateKeyFromBase64String(priKeyStr);
            } else {
                /*从本地证书文件获取*/
                List<String> aliasList = RSAUtil.getCertAliasFromPfxCertFile(encryptCertInfo.getCertSavePath(), encryptCertInfo.getCertPassword());
                privateKey = RSAUtil.getPrivateKeyFromCertFile(encryptCertInfo.getCertSavePath(), aliasList.get(0), encryptCertInfo.getCertPassword());
                if (privateKey != null) {
                    if (UnifiedCache.set(UpacParamConstant.CERT_KEY_CACHE, encryptCertInfo.getCertIndex(), Base64.encodeBase64String(privateKey.getEncoded())) != 0) {
                        rglog.error("设置证书缓存索引号{}缓存失败", encryptCertInfo.getCertIndex());
                    }
                }
            }
            return UpacSecurityUtil.decryptData(encData, privateKey, encoding);
        }
    }

    /**
     * 支付标识化信息KV转换处理
     *
     * @param tokenPayInfo 支付标记化信息
     */
    protected void packageTokenPayInfo(TokenPayInfo tokenPayInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        StringBuffer tokenPayData = new StringBuffer(UpacParamConstant.LEFT_BRACE);
        if (null != tokenPayInfo.getToken() && !tokenPayInfo.getToken().isEmpty()) {
            tokenPayData.append(UpacTreeNodeConstant.token + UpacParamConstant.EQUAL + tokenPayInfo.getToken() + UpacParamConstant.AMPERSAND);
        }
        if (null != tokenPayInfo.getTrId() && !tokenPayInfo.getTrId().isEmpty()) {
            tokenPayData.append(UpacTreeNodeConstant.trId + UpacParamConstant.EQUAL + tokenPayInfo.getTrId() + UpacParamConstant.AMPERSAND);
        }
        if (null != tokenPayInfo.getTokenLevel() && !tokenPayInfo.getTokenLevel().isEmpty()) {
            tokenPayData.append(UpacTreeNodeConstant.tokenLevel + UpacParamConstant.EQUAL + tokenPayInfo.getTokenLevel() + UpacParamConstant.AMPERSAND);
        }
        if (null != tokenPayInfo.getTokenBegin() && !tokenPayInfo.getTokenBegin().isEmpty()) {
            tokenPayData.append(UpacTreeNodeConstant.tokenBegin + UpacParamConstant.EQUAL + tokenPayInfo.getTokenBegin() + UpacParamConstant.AMPERSAND);
        }
        if (null != tokenPayInfo.getTokenEnd() && !tokenPayInfo.getTokenEnd().isEmpty()) {
            tokenPayData.append(UpacTreeNodeConstant.tokenEnd + UpacParamConstant.EQUAL + tokenPayInfo.getTokenEnd() + UpacParamConstant.AMPERSAND);
        }
        if (null != tokenPayInfo.getTokenType() && !tokenPayInfo.getTokenType().isEmpty()) {
            tokenPayData.append(UpacTreeNodeConstant.tokenType + UpacParamConstant.EQUAL + tokenPayInfo.getTokenType() + UpacParamConstant.AMPERSAND);
        }
        tokenPayData.setLength(tokenPayData.length() - 1);
        tokenPayData.append(UpacParamConstant.RIGHT_BRACE);
        xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.tokenPayData, tokenPayData.toString());
    }

    /**
     * 个人身份及认证信息加密处理
     *
     * @param customerInfo 个人身份及认证信息
     * @param cardNo       支付账号
     * @throws Exception 异常
     */
    protected void packageCustomerInfo(CustomerInfo customerInfo, String cardNo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
        CertInfo encryptCertInfo = null;
        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(UpacTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);
        String encoding = UpacParamConstant.UTF_8_ENCODING;

        StringBuffer customerEncryptInfo = new StringBuffer(UpacParamConstant.LEFT_BRACE);
        if (null != customerInfo.getCertType() && !customerInfo.getCertType().isEmpty()) {
            customerEncryptInfo.append(UpacTreeNodeConstant.certType + UpacParamConstant.EQUAL + customerInfo.getCertType() + UpacParamConstant.AMPERSAND);
        }
        if (null != customerInfo.getCertNo() && !customerInfo.getCertNo().isEmpty()) {
            customerEncryptInfo.append(UpacTreeNodeConstant.certNo + UpacParamConstant.EQUAL + customerInfo.getCertNo() + UpacParamConstant.AMPERSAND);
        }
        if (null != customerInfo.getCustName() && !customerInfo.getCustName().isEmpty()) {
            customerEncryptInfo.append(UpacTreeNodeConstant.custName + UpacParamConstant.EQUAL + customerInfo.getCustName() + UpacParamConstant.AMPERSAND);
        }
        if (null != customerInfo.getAuthCode() && !customerInfo.getAuthCode().isEmpty()) {
            customerEncryptInfo.append(UpacTreeNodeConstant.smsCode + UpacParamConstant.EQUAL + customerInfo.getAuthCode() + UpacParamConstant.AMPERSAND);
        }
        if (null != customerInfo.getCvn2() || null != customerInfo.getPhoneNo() || null != customerInfo.getExpiryDate() || null != customerInfo.getPinData()) {
            /* 获取敏感信息解密证书 */
            List<SecPlanInfo> secPlanInfoList = null;
            String secPlanInfoListString = xmlTreeUtil.getXmlTreeStringValue(UpacTreeNodeConstant.SEC_PLAN_INFO_LIST);
            if (secPlanInfoListString == null) {
                /* 根据通道安全计划获取安全计划 */
                SecPlanInfoMapper secPlanInfoMapper = new SecPlanInfoMapperImpl();
                secPlanInfoList = secPlanInfoMapper.selectSecPlanInfoBySecPlanId(instId, dstChannelInfo.getSecPlanId());
                if (null != secPlanInfoList && !secPlanInfoList.isEmpty()) {
                    xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.SEC_PLAN_INFO_LIST, JSON.toJSONString(secPlanInfoList));
                } else {
                    rglog.error("获取通道解密密钥证书失败！");
                    return;
                }
            }
            /* 获取敏感信息加密证书 */
            Optional<SecPlanInfo> encryptSecPlanOpt = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(UpacParamConstant.ENCRYPT_CERT_TYPE)).findFirst();
            if (encryptSecPlanOpt.isPresent()) {
                CertInfoMapper certInfoMapper = new CertInfoMapperImpl();
                encryptCertInfo = certInfoMapper.selectCertInfoByPrimaryKey(instId + encryptSecPlanOpt.get().getSecPlanId() + encryptSecPlanOpt.get().getSecPlanType());
            }
        }
        /* 客户密钥加密 */
        if (null != customerInfo.getPinData() && !customerInfo.getPinData().isEmpty()) {
            if (null == cardNo || cardNo.trim().isEmpty()) {
                rglog.error("客户送了密码（PIN），必须上传卡号！");
                throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            }
            String encryptPinData = UpacSecurityUtil.encryptPinData(cardNo, customerInfo.getPinData(), encryptCertInfo.getCertValue(), encoding);
            customerEncryptInfo.append(UpacTreeNodeConstant.pinData + UpacParamConstant.EQUAL + encryptPinData + UpacParamConstant.AMPERSAND);
        }
        /* 敏感信息加密 */
        StringBuffer encryptedInfo = new StringBuffer(UpacParamConstant.BLANK);
        if (null != customerInfo.getPhoneNo() && !customerInfo.getPhoneNo().isEmpty()) {
            encryptedInfo.append(UpacTreeNodeConstant.phoneNo).append(UpacParamConstant.EQUAL).append(customerInfo.getPhoneNo()).append(UpacParamConstant.AMPERSAND);
        }
        if (null != customerInfo.getCvn2() && !customerInfo.getCvn2().isEmpty()) {
            encryptedInfo.append(UpacTreeNodeConstant.cvn2).append(UpacParamConstant.EQUAL).append(customerInfo.getCvn2()).append(UpacParamConstant.AMPERSAND);
        }
        if (null != customerInfo.getExpiryDate() && !customerInfo.getExpiryDate().isEmpty()) {
            encryptedInfo.append(UpacTreeNodeConstant.expired).append(UpacParamConstant.EQUAL).append(customerInfo.getExpiryDate()).append(UpacParamConstant.AMPERSAND);
        }
        if (!"".equals(encryptedInfo.toString())) {
            xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.encryptCertId, encryptCertInfo.getCertId());
            encryptedInfo.setLength(encryptedInfo.length() - 1);
            String encryptData = UpacSecurityUtil.encryptData(encryptedInfo.toString(), encryptCertInfo.getCertValue(), encoding);
            customerEncryptInfo.append(UpacTreeNodeConstant.encryptedInfo + UpacParamConstant.EQUAL + encryptData);
            //customerEncryptInfo.append(UpacParamConstant.encryptedInfo + UpacParamConstant.EQUAL + encryptData + UpacParamConstant.AMPERSAND);
        } else {
            customerEncryptInfo.setLength(customerEncryptInfo.length() - 1);
        }
        customerEncryptInfo.append(UpacParamConstant.RIGHT_BRACE);
        String customerInfoString = new String(Base64.encodeBase64(customerEncryptInfo.toString().getBytes(encoding)), encoding);
        xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.customerInfo, customerInfoString);
    }

    /**
     * 风控信息KV转换处理
     *
     * @param riskCtrlInfo 风控信息
     * @throws Exception 异常
     */
    protected void packageRiskCtrlInfo(RiskCtrlInfo riskCtrlInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        StringBuffer riskCtrlData = new StringBuffer(UpacParamConstant.LEFT_BRACE);
        if (null != riskCtrlInfo.getShippingFlag() && !riskCtrlInfo.getShippingFlag().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.shippingFlag + UpacParamConstant.EQUAL + riskCtrlInfo.getShippingFlag() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getShippingCountry() && !riskCtrlInfo.getShippingCountry().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.shippingCountryCode + UpacParamConstant.EQUAL + riskCtrlInfo.getShippingCountry() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getShippingProvince() && !riskCtrlInfo.getShippingProvince().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.shippingProvinceCode + UpacParamConstant.EQUAL + riskCtrlInfo.getShippingProvince() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getShippingCity() && !riskCtrlInfo.getShippingCity().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.shippingCityCode + UpacParamConstant.EQUAL + riskCtrlInfo.getShippingCity() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getShippingArea() && !riskCtrlInfo.getShippingArea().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.shippingDistrictCode + UpacParamConstant.EQUAL + riskCtrlInfo.getShippingArea() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getShippingStreet() && !riskCtrlInfo.getShippingStreet().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.shippingStreet + UpacParamConstant.EQUAL + riskCtrlInfo.getShippingStreet() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getGoodCategory() && !riskCtrlInfo.getGoodCategory().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.commodityCategory + UpacParamConstant.EQUAL + riskCtrlInfo.getGoodCategory() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getGoodName() && !riskCtrlInfo.getGoodName().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.commodityName + UpacParamConstant.EQUAL + riskCtrlInfo.getGoodName() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getGoodUrl() && !riskCtrlInfo.getGoodUrl().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.commodityUrl + UpacParamConstant.EQUAL + riskCtrlInfo.getGoodUrl() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getGoodPrice() && !riskCtrlInfo.getGoodPrice().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.commodityUnitPrice + UpacParamConstant.EQUAL + riskCtrlInfo.getGoodPrice() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getGoodNum() && !riskCtrlInfo.getGoodNum().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.commodityQty + UpacParamConstant.EQUAL + riskCtrlInfo.getGoodNum() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getShippingMobile() && !riskCtrlInfo.getShippingMobile().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.shippingMobile + UpacParamConstant.EQUAL + riskCtrlInfo.getShippingMobile() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getAddrModifyTime() && !riskCtrlInfo.getAddrModifyTime().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.addressModifyTime + UpacParamConstant.EQUAL + riskCtrlInfo.getAddrModifyTime() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getUserRegisterTime() && !riskCtrlInfo.getUserRegisterTime().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.userRegisterTime + UpacParamConstant.EQUAL + riskCtrlInfo.getUserRegisterTime() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getReceiptNameModifyTime() && !riskCtrlInfo.getReceiptNameModifyTime().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.orderNameModifyTime + UpacParamConstant.EQUAL + riskCtrlInfo.getReceiptNameModifyTime() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getUserId() && !riskCtrlInfo.getUserId().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.userId + UpacParamConstant.EQUAL + riskCtrlInfo.getUserId() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getReceiptName() && !riskCtrlInfo.getReceiptName().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.orderName + UpacParamConstant.EQUAL + riskCtrlInfo.getReceiptName() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getUserFlag() && !riskCtrlInfo.getUserFlag().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.userFlag + UpacParamConstant.EQUAL + riskCtrlInfo.getUserFlag() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getMobileModifyTime() && !riskCtrlInfo.getMobileModifyTime().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.mobileModifyTime + UpacParamConstant.EQUAL + riskCtrlInfo.getMobileModifyTime() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getRiskLevel() && !riskCtrlInfo.getRiskLevel().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.riskLevel + UpacParamConstant.EQUAL + riskCtrlInfo.getRiskLevel() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getMchntUserId() && !riskCtrlInfo.getMchntUserId().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.merUserId + UpacParamConstant.EQUAL + riskCtrlInfo.getMchntUserId() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getMchntUserRegTime() && !riskCtrlInfo.getMchntUserRegTime().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.merUserRegDt + UpacParamConstant.EQUAL + riskCtrlInfo.getMchntUserRegTime() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getMchntUserRegEmail() && !riskCtrlInfo.getMchntUserRegEmail().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.merUserEmail + UpacParamConstant.EQUAL + riskCtrlInfo.getMchntUserRegEmail() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getDiskSeqNo() && !riskCtrlInfo.getDiskSeqNo().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.diskSep + UpacParamConstant.EQUAL + riskCtrlInfo.getDiskSeqNo() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getImei() && !riskCtrlInfo.getImei().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.imei + UpacParamConstant.EQUAL + riskCtrlInfo.getImei() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getImei() && !riskCtrlInfo.getImei().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.imei + UpacParamConstant.EQUAL + riskCtrlInfo.getImei() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getMacAddr() && !riskCtrlInfo.getMacAddr().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.macAddr + UpacParamConstant.EQUAL + riskCtrlInfo.getMacAddr() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getLongitudeAndLatitude() && !riskCtrlInfo.getLongitudeAndLatitude().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.lbs + UpacParamConstant.EQUAL + riskCtrlInfo.getLongitudeAndLatitude() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getDeviceNo() && !riskCtrlInfo.getDeviceNo().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.deviceNumber + UpacParamConstant.EQUAL + riskCtrlInfo.getDeviceNo() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getDeviceType() && !riskCtrlInfo.getDeviceType().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.deviceType + UpacParamConstant.EQUAL + riskCtrlInfo.getDeviceType() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getCaptureMethod() && !riskCtrlInfo.getCaptureMethod().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.captureMethod + UpacParamConstant.EQUAL + riskCtrlInfo.getCaptureMethod() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getSimCardNum() && !riskCtrlInfo.getSimCardNum().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.simCardCount + UpacParamConstant.EQUAL + riskCtrlInfo.getSimCardNum() + UpacParamConstant.AMPERSAND);
        }
        if (null != riskCtrlInfo.getDeviceName() && !riskCtrlInfo.getDeviceName().isEmpty()) {
            riskCtrlData.append(UpacTreeNodeConstant.deviceName + UpacParamConstant.EQUAL + riskCtrlInfo.getDeviceName() + UpacParamConstant.AMPERSAND);
        }
        if (riskCtrlData.length() > 1) {
            riskCtrlData.setLength(riskCtrlData.length() - 1);
            riskCtrlData.append(UpacParamConstant.RIGHT_BRACE);
            xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.riskRateInfo, riskCtrlData.toString());
        }
    }

    /**
     * 付款方信息域kv转换处理
     *
     * @param payerInfo
     * @throws Exception
     */
    protected void packagePayerInfo(PayerInfo payerInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        StringBuffer payerVerifiInfo = new StringBuffer(UpacParamConstant.LEFT_BRACE);
        if (null != payerInfo.getPayerAccNo() && !payerInfo.getPayerAccNo().isEmpty()) {
            payerVerifiInfo.append(UpacTreeNodeConstant.payerAccNo + UpacParamConstant.EQUAL + payerInfo.getPayerAccNo() + UpacParamConstant.AMPERSAND);
        }
        if (null != payerInfo.getPayerName() && !payerInfo.getPayerName().isEmpty()) {
            payerVerifiInfo.append(UpacTreeNodeConstant.payerNm + UpacParamConstant.EQUAL + payerInfo.getPayerName() + UpacParamConstant.AMPERSAND);
        }
        payerVerifiInfo.setLength(payerVerifiInfo.length() - 1);
        payerVerifiInfo.append(UpacParamConstant.RIGHT_BRACE);
        xmlTreeUtil.setXmlTreeStringValue(UpacTreeNodeConstant.payerVerifiInfo, payerVerifiInfo.toString());
    }

    protected <T> T convertKvStr2Bean(String kvStr, Class<T> beanClass) throws Exception {
        Map<String, Object> kvMap = UpacSecurityUtil.parseKvString(kvStr);
        JSONObject jsonObject = new JSONObject(kvMap);
        return JSON.parseObject(jsonObject.toJSONString(), beanClass);
    }

    protected String convertRespCode(String srcRespCode) {
        if (UpacParamConstant.SUCCESS_CODE.equals(srcRespCode) ||
                UpacParamConstant.DEFECT_SUCCESS_CODE.equals(srcRespCode)) {
            return OltpRpcdEnum.TRANS_SUCCESS.getRespCode();
        } else if ("03".equals(srcRespCode) || "05".equals(srcRespCode) || "12".equals(srcRespCode)) {
            return OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode();
        } else {
            return srcRespCode;
        }
    }
}
